/*
 * Wazuh Vulnerability scanner - Scan Orchestrator
 * Copyright (C) 2015, Wazuh Inc.
 * May 2, 2024.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#ifndef _HOTFIX_INSERT_HPP
#define _HOTFIX_INSERT_HPP

#include "chainOfResponsability.hpp"
#include "databaseFeedManager.hpp"
#include "inventorySync.hpp"
#include "remediationDataCache.hpp"
#include "scanContext.hpp"
#include "stringHelper.h"
#include <unordered_set>

/**
 * @brief TEventInsertInventory class.
 * This class is in charge of inserting the inventory entries for a given agent and affected component type.
 * It receives the scan context and the inventory database and returns the scan context with the inventory updated.
 * The affected component type can be Os or Package.
 * Os: Insert inventory of the OS for the agent.
 * Package: Insert a package into the inventory for the agent.
 *
 * @tparam TScanContext scan context type.
 */
template<typename TDatabaseFeedManager = DatabaseFeedManager, typename TScanContext = ScanContext>
class THotfixInsert final : public AbstractHandler<std::shared_ptr<TScanContext>>
{
private:
    std::shared_ptr<TDatabaseFeedManager> m_databaseFeedManager;

public:
    // LCOV_EXCL_START
    /**
     * @brief HotfixInsert event constructor.
     *
     * @param databaseFeedManager Database feed manager.
     */
    explicit THotfixInsert(std::shared_ptr<TDatabaseFeedManager>& databaseFeedManager)
        : m_databaseFeedManager(databaseFeedManager)
    {
    }
    // LCOV_EXCL_STOP

    /**
     * @brief Handles request and passes control to the next step of the chain.
     *
     * @param data Scan context.
     * @return std::shared_ptr<ScanContext> Abstract handler.
     */
    std::shared_ptr<TScanContext> handleRequest(std::shared_ptr<TScanContext> data) override
    {
        const std::string hotfixId {data->hotfixId()};
        if (hotfixId.empty())
        {
            logDebug2(WM_VULNSCAN_LOGTAG, "No hotfix installed");
            return nullptr;
        }

        logDebug2(WM_VULNSCAN_LOGTAG, "Getting associated vulnerabilities for hotfix '%s'", hotfixId.c_str());
        const std::unordered_set<std::string> hotfixVulnerabilities =
            m_databaseFeedManager->getHotfixVulnerabilities(hotfixId);

        if (hotfixVulnerabilities.empty())
        {
            logDebug2(WM_VULNSCAN_LOGTAG, "No vulnerabilities associated to hotfix '%s'", hotfixId.c_str());
            return nullptr;
        }

        for (const auto& hotfixVulnerability : hotfixVulnerabilities)
        {
            const auto cveId = hotfixVulnerability.substr(hotfixId.size() + 1);

            data->m_elements[cveId] = nlohmann::json::array();
        }

        return AbstractHandler<std::shared_ptr<TScanContext>>::handleRequest(std::move(data));
    }
};

using HotfixInsert = THotfixInsert<>;

#endif // _HOTFIX_INSERT_HPP
